﻿using System;
using Csla;
using log4net;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using Sireass.Bl.Rules;

namespace Sireass.Bl
{
    [Serializable]
    public class AsignacionEdit : BusinessBase<AsignacionEdit>
    {
        // Create a logger for use in this class
        private static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        #region Propiedades
     
        public static readonly PropertyInfo<long> IdAsignacionProperty = RegisterProperty<long>(c => c.IdAsignacion);
        [Display(Name = "Id de la Asignacion")]
        public long IdAsignacion
        {
            get { return GetProperty(IdAsignacionProperty); }
            private set { LoadProperty(IdAsignacionProperty, value); }
        }

        public static readonly PropertyInfo<long> IdPrestadorProperty = RegisterProperty<long>(c => c.IdPrestador);
        [Display(Name = "Id del prestador")]
		[Required(ErrorMessage="Debe indicar el Prestador de Servicio Social")]
        public long IdPrestador
        {
            get { return GetProperty(IdPrestadorProperty); }
            set { SetProperty(IdPrestadorProperty, value); }
        }

        public static readonly PropertyInfo<string> EncargadoProyectoProperty = RegisterProperty<string>(c => c.EncargadoProyecto);
        [Display(Name = "Encargado Proyecto")]
        public string EncargadoProyecto
        {
            get { return GetProperty(EncargadoProyectoProperty); }
            private set { LoadProperty(EncargadoProyectoProperty, value); }
        }

        public static readonly PropertyInfo<long> IdEncargadoProyectoProperty = RegisterProperty<long>(c => c.IdEncargadoProyecto);
        [Display(Name = "Id Encargado Proyecto")]
		[Required(ErrorMessage = "Debe indicar el Encargado")]
        public long IdEncargadoProyecto
        {
            get { return GetProperty(IdEncargadoProyectoProperty); }
            set { SetProperty(IdEncargadoProyectoProperty, value); }
        }

        public static readonly PropertyInfo<string> PrestadorProperty = RegisterProperty<string>(c => c.Prestador);
        [Display(Name = "Prestador")]
        public string Prestador
        {
            get { return GetProperty(PrestadorProperty); }
            private set { LoadProperty(PrestadorProperty, value); }
        }

        public static readonly PropertyInfo<long> IdProyectoProperty = RegisterProperty<long>(c => c.IdProyecto);
        [Display(Name = "Id del Proyecto")]
		[Required(ErrorMessage = "Debe indicar el Proyecto")]
        public long IdProyecto
        {
            get { return GetProperty(IdProyectoProperty); }
            set { SetProperty(IdProyectoProperty, value); }
        }

        public static readonly PropertyInfo<Int32> IdEstatusProperty = RegisterProperty<Int32>(c => c.IdEstatus);
        [Display(Name = "Id del Estatus")]
        public Int32 IdEstatus
        {
            get { return GetProperty(IdEstatusProperty); }
            private set { SetProperty(IdEstatusProperty, value); }
        }

        public static readonly PropertyInfo<string> EstatusProperty = RegisterProperty<string>(c => c.Estatus);
        [Display(Name = "Estatus")]
        public string Estatus
        {
            get { return GetProperty(EstatusProperty); }
            private set { LoadProperty(EstatusProperty, value); }
        }

        public static readonly PropertyInfo<DateTime> FechaInicioAsignacionProperty = RegisterProperty<DateTime>(c => c.FechaInicioAsignacion);
        [Display(Name = "Fecha Inicio Asignacion")]
		[Required(ErrorMessage = "Debe indicar la Fecha de Inicio de Asignación")]
        public DateTime FechaInicioAsignacion
        {
            get { return GetProperty(FechaInicioAsignacionProperty); }
            set { SetProperty(FechaInicioAsignacionProperty, value); }
        }

        public static readonly PropertyInfo<DateTime> FechaFinAsignacionProperty = RegisterProperty<DateTime>(c => c.FechaFinAsignacion);
        [Display(Name = "Fecha Fin Asignacion")]
		[Required(ErrorMessage = "Debe indicar la Fecha de Fin de Asignación")]
        public DateTime FechaFinAsignacion
        {
            get { return GetProperty(FechaFinAsignacionProperty); }
            set { SetProperty(FechaFinAsignacionProperty, value); }
        }

        public static readonly PropertyInfo<Int16> HorasPorAplicarProperty = RegisterProperty<Int16>(c => c.HorasPorAplicar);
        [Display(Name = "Horas por aplicar")]
		[Required(ErrorMessage="Debe indicar las Horas por aplicar")]		
        public Int16 HorasPorAplicar
        {
            get { return GetProperty(HorasPorAplicarProperty); }
            set { SetProperty(HorasPorAplicarProperty, value); }
        }

        public static readonly PropertyInfo<bool> HabilitadoProperty = RegisterProperty<bool>(c => c.Habilitado);
        [Display(Name = "Habilitado")]
        public bool Habilitado
        {
            get { return GetProperty(HabilitadoProperty); }
            private set { SetProperty(HabilitadoProperty, value); }
        }

        public static readonly PropertyInfo<DateTime> FechaAltaProperty = RegisterProperty<DateTime>(c => c.FechaAlta);
        [Display(Name = "Fecha Alta")]
        public DateTime FechaAlta
        {
            get { return GetProperty(FechaAltaProperty); }
            private set { LoadProperty(FechaAltaProperty, value); }
        }

        public static readonly PropertyInfo<DateTime> FechaBajaProperty = RegisterProperty<DateTime>(c => c.FechaBaja);
        [Display(Name = "Fecha Baja")]
        public DateTime FechaBaja
        {
            get { return GetProperty(FechaBajaProperty); }
            private set { LoadProperty(FechaBajaProperty, value); }
        }

        #endregion

        #region Factory

        private AsignacionEdit() { }

        public static void NewAsignacionEdit(EventHandler<DataPortalResult<AsignacionEdit>> callback)
        {
            DataPortal.BeginCreate<AsignacionEdit>(callback);
        }

        public static AsignacionEdit NewAsignacionEdit()
        {
            return DataPortal.Create<AsignacionEdit>();
        }

        public static void GetAsignacionEdit(long id, EventHandler<DataPortalResult<AsignacionEdit>> callback)
        {
            DataPortal.BeginFetch<AsignacionEdit>(id, callback);
        }

        public static AsignacionEdit GetAsignacionEdit(long id)
        {
            return DataPortal.Fetch<AsignacionEdit>(id);
        }

        public static void DeleteProyectoEdit(long id)
        {
            DataPortal.Delete<AsignacionEdit>(id);
        }

        #endregion

        #region Métodos
        public static void AddObjectAuthorizationRules()
        {
            Type type = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType;
            PerfilServicioCriteria criteria = new PerfilServicioCriteria(type.FullName, true);
            PerfilServicioList perfilesPorServicio = PerfilServicioList.GetPerfilServicioList(criteria);
            List<string> roles = new List<string>(perfilesPorServicio.Count);
            foreach (PerfilServicioInfo perfilServicio in perfilesPorServicio)
            {
                roles.Add(perfilServicio.Perfil);
            }
            Csla.Rules.BusinessRules.AddRule(type, new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.CreateObject, roles));
            Csla.Rules.BusinessRules.AddRule(type, new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.GetObject, roles));
            Csla.Rules.BusinessRules.AddRule(type, new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.EditObject, roles));
            Csla.Rules.BusinessRules.AddRule(type, new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.DeleteObject, roles));
        }

		protected override void AddBusinessRules() 
		{ 
			base.AddBusinessRules();			
			//ToDo: Validar que la regla de negocio que indica que las horas sean mayores a cero, sea correcta
			//ToDo: Parametrizar el mínimo y máximo de las horas por aplicar
			BusinessRules.AddRule(new Csla.Rules.CommonRules.MinValue<double>(HorasPorAplicarProperty, 1, "Las Horas por aplicar deben ser mayores a cero"));
			BusinessRules.AddRule(new Csla.Rules.CommonRules.MaxValue<double>(HorasPorAplicarProperty, 999.99, "Las Horas por aplicar deben ser menores a 1000"));
			BusinessRules.AddRule(new ValidaPeriodo(FechaInicioAsignacionProperty, FechaFinAsignacionProperty) { Priority = 1 });
			BusinessRules.AddRule(new Csla.Rules.CommonRules.Dependency(FechaInicioAsignacionProperty, FechaFinAsignacionProperty) { Priority = 1 });
		}
        #endregion

        #region Data Portal

        [RunLocal]
        protected override void DataPortal_Create()
        {
            using (BypassPropertyChecks)
            {
                IdAsignacion = -1;
				//Cuando se crea una asignación debe estar Activa y Habilitada por defecto
				IdEstatus = (int)Enums.EstatusAsignacion.Activa;
				Habilitado = true;
            }
            base.DataPortal_Create();
        }

        private void DataPortal_Fetch(long id)
        {
            using (var dalManager = Sireass.Dal.DalFactory.GetManager())
            {
                var dal = dalManager.GetProvider<Sireass.Dal.IAsignacionDal>();
                using (var data = new Csla.Data.SafeDataReader(dal.Fetch(id)))
                {
                    data.Read();
                    using (BypassPropertyChecks)
                    {
                        IdAsignacion = data.GetInt64("nId_Asignacion");
                        IdPrestador = data.GetInt64("nId_Prestador");
                        Prestador = data.GetString("cPrestador");
                        IdEncargadoProyecto = data.GetInt64("nld_Proyecto_Encargado");
                        EncargadoProyecto = data.GetString("cProyectoEncargado");
                        IdProyecto = data.GetInt64("nId_Proyecto");
                        IdEstatus = data.GetInt32("nId_Estatus_Asignacion");
                        Estatus = data.GetString("cEstatusAsignacion");
                        FechaInicioAsignacion = data.GetDateTime("dFecha_Inicio_Asignacion");
                        FechaFinAsignacion = data.GetDateTime("dFecha_Fin_Asignacion");
                        HorasPorAplicar = data.GetInt16("nHorasPorAplicar");
                        Habilitado = data.GetBoolean("bHabilitado");
                        FechaAlta = data.GetDateTime("dFecha_Alta");
                        FechaBaja = data.GetDateTime("dFecha_Baja");
                    }
                }
            }
            BusinessRules.CheckRules();
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        protected override void DataPortal_Insert()
        {
            using (var dalManager = Sireass.Dal.DalFactory.GetManager())
            {
                var dal = dalManager.GetProvider<Sireass.Dal.IAsignacionDal>();
                using (BypassPropertyChecks)
                {
                    IdAsignacion = dal.Insert(IdPrestador, IdEncargadoProyecto, IdProyecto ,IdEstatus, Habilitado,  
                        HorasPorAplicar, FechaInicioAsignacion, FechaFinAsignacion);
                }
            }
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        protected override void DataPortal_Update()
        {
            using (var dalManager = Sireass.Dal.DalFactory.GetManager())
            {
                var dal = dalManager.GetProvider<Sireass.Dal.IAsignacionDal>();
                using (BypassPropertyChecks)
                {
                    dal.Update(IdAsignacion, IdPrestador, IdEncargadoProyecto, IdProyecto , IdEstatus, Habilitado, HorasPorAplicar);
                }
            }
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        protected override void DataPortal_DeleteSelf()
        {
            using (BypassPropertyChecks)
            {
                DataPortal_Delete(IdAsignacion);
            }
        }

        [Transactional(TransactionalTypes.TransactionScope)]
        private void DataPortal_Delete(long id)
        {
            using (var dalManager = Sireass.Dal.DalFactory.GetManager())
            {
                var dal = dalManager.GetProvider<Sireass.Dal.IAsignacionDal>();
                dal.Delete(id);
            }
        }

        //[Transactional(TransactionalTypes.TransactionScope)]
        //protected override bool DataPortal_Update()
        //{
        //    using (var dalManager = Sireass.Dal.DalFactory.GetManager())
        //    {
        //        var dal = dalManager.GetProvider<Sireass.Dal.IAsignacionDal>();
        //        using (BypassPropertyChecks)
        //        {
        //            return dal.Update(IdAsignacion, IdEstatus, Habilitado, FechaBaja);
        //        }
        //    }
        //}

        protected override void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
        {
            // implement your behavior here
            base.DataPortal_OnDataPortalInvoke(e);
        }

        protected override void DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
        {
            // implement your behavior here
            base.DataPortal_OnDataPortalInvokeComplete(e);
        }

        protected override void Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
        {
            // implement your behavior here
            base.Child_OnDataPortalException(e, ex);
        }
        #endregion

		#region Child Data Portal
		protected override void Child_Create()
		{
			using (BypassPropertyChecks)
			{
				IdAsignacion = -1;
				//Cuando se crea una asignación debe estar Activa y Habilitada por defecto
				IdEstatus = (int)Enums.EstatusAsignacion.Activa;
				Habilitado = true;
			}
			base.Child_Create();
		}

		private void Child_Fetch(long id)
		{
			DataPortal_Fetch(id);
		}

		private void Child_Insert()
		{
			DataPortal_Insert();
		}

		private void Child_Update()
		{
			DataPortal_Update();
		}

		private void Child_DeleteSelf()
		{
			DataPortal_DeleteSelf();
		}

		private void Child_Delete(long id)
		{
			DataPortal_Delete(id);
		}
		#endregion
	}
}
